package com.dhcc.common.utils.hql;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.persistence.Column;
import javax.persistence.Transient;

import com.dhcc.framework.exception.DataBaseException;

/**
 * 
* <p>描述: 根据对象生成HQL语句的工具类</p>
* <p>公司: 东华医为</p>
* <p>版权: dhcc2018</p>
* @author  250000576@qq.com
* @date 2015年2月27日 下午5:17:30
* @version V1.0
 */
public class GetHql {
	private static final List<String> PRIMITIVE_DATA_TYPE_LIST=new ArrayList<String>();
	static{
		PRIMITIVE_DATA_TYPE_LIST.add("short");
		PRIMITIVE_DATA_TYPE_LIST.add("int");
		PRIMITIVE_DATA_TYPE_LIST.add("long");
		PRIMITIVE_DATA_TYPE_LIST.add("float");
		PRIMITIVE_DATA_TYPE_LIST.add("double");
		PRIMITIVE_DATA_TYPE_LIST.add("boolean");
		PRIMITIVE_DATA_TYPE_LIST.add("char");
		PRIMITIVE_DATA_TYPE_LIST.add("byte");
	}
	
	private GetHql() {
	}

	/**
	 * 
	* 根据对象生成HQL语句
	* @param obj 数据对象
	* @param hqlStr 需要修改的HQL字符串对象
	* @param map 键值对集合
	* @param list 不需要作为查询条件的属性
	 */
	public static void getHqlByObject(Object obj,StringBuilder hqlStr,Map<String, Object> map,List<String> list) {
		if (obj==null) {
			return;
		}
		if(hqlStr.length()==0){
			hqlStr.append("from ").append(obj.getClass().getName()).append(" where 1=1");
		}
		list.add("serialVersionUID");
		// 获取f对象对应类中的所有属性域
		Field[] fields = obj.getClass().getDeclaredFields();
		int j=0;
		for(int i = 0 , len = fields.length; i < len; i++) {
			// 对于每个属性，获取属性名
			String varName = fields[i].getName();
			if (list.contains(varName)) {
				continue;
			}
			try {
				// 获取原来的访问控制权限
				boolean accessFlag = fields[i].isAccessible();
				// 修改访问控制权限
				fields[i].setAccessible(true);
				// 获取在对象f中属性fields[i]对应的对象中的变量
				Object varValue = fields[i].get(obj);
				if ((varValue!=null)&&(!"".equals(varValue))) {
					j++;
					hqlStr.append(" And ").append(varName).append("=:varValue").append(j);
					map.put("varValue"+j, varValue);
				}
				// 恢复访问控制权限
				fields[i].setAccessible(accessFlag);
			} catch (Exception e) {
				throw new DataBaseException(e.getMessage(), e);
			}
		}
	}
	
	public static void getHqlByObject(Object obj,StringBuilder hqlStr,Map<String, Object> map,
			List<String> list,String alias) {
		if (obj==null) {
			return;
		}
		if(hqlStr.length()==0){
			hqlStr.append("from ").append(obj.getClass().getName()).append(" ").append(alias).append(" where 1=1");
		}
		list.add("serialVersionUID");
		// 获取f对象对应类中的所有属性域
		Field[] fields = obj.getClass().getDeclaredFields();
		for(int i = 0 , len = fields.length; i < len; i++) {
			// 对于每个属性，获取属性名
			String varName = fields[i].getName();
			if (list.contains(varName)) {
				continue;
			}
			try {
				// 获取原来的访问控制权限
				boolean accessFlag = fields[i].isAccessible();
				// 修改访问控制权限
				fields[i].setAccessible(true);
				// 获取在对象f中属性fields[i]对应的对象中的变量
				Object varValue = fields[i].get(obj);
				if (!fields[i].getType().getName().startsWith("java.")
						&&!PRIMITIVE_DATA_TYPE_LIST.contains(fields[i].getType().getName())
						&&varValue!=null) {
					getHqlByObject(varValue,hqlStr,map,list,alias+"."+varName);
				}else if ((varValue!=null)&&(!"".equals(varValue))) {
					hqlStr.append(" And ").append(alias).append(".").append(varName).append(" like:").append(alias.replace(".", "")).append(varName);
					map.put(alias.replace(".", "")+varName, "%"+varValue+"%");
				}
				// 恢复访问控制权限
				fields[i].setAccessible(accessFlag);
			} catch (Exception e) {
				throw new DataBaseException(e.getMessage(), e);
			}
		}
	}

	/**
	 * 
	* 根据对象生成更新的HQL语句
	* @param obj 数据对象
	* @param hqlStr 需要修改的HQL字符串对象
	* @param map 键值对集合
	* @param list 不需要作为查询条件的属性
	* @param idName 主键属性名称
	* @return 1表示成功，0表示失败
	 */
	public static int getUpdateHqlByObject(Object obj,StringBuilder hqlStr,Map<String, Object> map,List<String> list,String idName) {
		if(hqlStr.length()==0){
			hqlStr.append("update ").append(obj.getClass().getName()).append(" set");
		}
		list.add("serialVersionUID");
		// update zabbix.interface set dns=?,hostid=? where interfaceid=?
		// 获取f对象对应类中的所有属性域
		Field[] fields = obj.getClass().getDeclaredFields();
		int j=0;
		int result=0;
		for(int i = 0 , len = fields.length; i < len; i++) {
			// 对于每个属性，获取属性名
			String varName = fields[i].getName();
			if (list.contains(varName)) {
				continue;
			}
			try {
				// 获取原来的访问控制权限
				boolean accessFlag = fields[i].isAccessible();
				// 修改访问控制权限
				fields[i].setAccessible(true);
				// 获取在对象f中属性fields[i]对应的对象中的变量
				Object varValue = fields[i].get(obj);
				if (varValue==null) {
					hqlStr.append(" ").append(varName).append("=").append(varValue).append(",");
				}else {
					j++;
					if (idName.equals(varName)) {
						map.put("idValue", varValue);
					}
					hqlStr.append(" ").append(varName).append("=:varValue").append(j).append(",");
					map.put("varValue"+j, varValue);
				}
				// 恢复访问控制权限
				fields[i].setAccessible(accessFlag);
			} catch (Exception e) {
				throw new DataBaseException(e.getMessage(), e);
			}
		}
		if ((map.get("idValue")!=null)&&(!"".equals(map.get("idValue")))) {
			hqlStr.deleteCharAt(hqlStr.length()-1).append(" where ").append(idName).append("=:idValue");
			result=1;
		}
		return result;
	}

	/**
	 * 
	* 根据对象生成更新的HQL语句，忽略null字段
	* @param obj 数据对象
	* @param hqlStr 需要修改的HQL字符串
	* @param map 键值对集合
	* @param list 不需要作为查询条件的属性
	* @param idName 主键属性名称
	* @return 1表示成功，0表示失败
	 */
	public static int getUpdateNotNullHqlByObject(Object obj,StringBuilder hqlStr,Map<String, Object> map,List<String> list,String idName) {
		if(hqlStr.length()==0){
			hqlStr.append("update ").append(obj.getClass().getName()).append(" set");
		}
		list.add("serialVersionUID");
		// update zabbix.interface set dns=?,hostid=? where interfaceid=?
		// 获取f对象对应类中的所有属性域
		Field[] fields = obj.getClass().getDeclaredFields();
		int j=0;
		int result=0;
		for(int i = 0 , len = fields.length; i < len; i++) {
			// 对于每个属性，获取属性名
			String varName = fields[i].getName();
			if (list.contains(varName)) {
				continue;
			}
			try {
				// 获取原来的访问控制权限
				boolean accessFlag = fields[i].isAccessible();
				// 修改访问控制权限
				fields[i].setAccessible(true);
				// 获取在对象f中属性fields[i]对应的对象中的变量
				Object varValue = fields[i].get(obj);
				if ((varValue!=null)&&(!"".equals(varValue))) {
					j++;
					if (idName.equals(varName)) {
						map.put("idValue", varValue);
					}
					hqlStr.append(" ").append(varName).append("=:varValue").append(j).append(",");
					map.put("varValue"+j, varValue);
				}
				// 恢复访问控制权限
				fields[i].setAccessible(accessFlag);
			} catch (Exception e) {
				throw new DataBaseException(e.getMessage(), e);
			}
		}
		if ((map.get("idValue")!=null)&&(!"".equals(map.get("idValue")))){
			hqlStr.deleteCharAt(hqlStr.length()-1).append(" where ").append(idName).append("=:idValue");
			result=1;
		}
		return result;
	}
	
	public static void getDeleteHqlByObject(Object obj,StringBuilder hqlStr,Map<String, Object> map,List<String> list) {
		if (obj==null) {
			return;
		}
		if(hqlStr.length()==0){
			hqlStr.append("delete from ").append(obj.getClass().getName()).append(" where 1=1");
		}
		// 获取f对象对应类中的所有属性域
		Field[] fields = obj.getClass().getDeclaredFields();
		for(int i = 0 , len = fields.length; i < len; i++) {
			// 对于每个属性，获取属性名
			String varName = fields[i].getName();
			if ("serialVersionUID".equals(varName)||list.contains(varName)) {
				continue;
			}
			try {
				// 获取原来的访问控制权限
				boolean accessFlag = fields[i].isAccessible();
				// 修改访问控制权限
				fields[i].setAccessible(true);
				// 获取在对象f中属性fields[i]对应的对象中的变量
				Object varValue = fields[i].get(obj);
				if ((varValue!=null)&&(!"".equals(varValue))) {
					// 获取数据库字段名
					Annotation anns = obj.getClass().getDeclaredField(varName).getAnnotation(Column.class);
					if (anns==null) {
						Annotation annsTr =obj.getClass().getDeclaredField(varName).getAnnotation(Transient.class);
						if (annsTr!=null) {
							continue;
						}
					}
					hqlStr.append(" And ").append(varName).append("=:varValue").append(i);
					map.put("varValue"+i, varValue);
				}
				// 恢复访问控制权限
				fields[i].setAccessible(accessFlag);
			} catch (Exception e) {
				throw new DataBaseException(e.getMessage(), e);
			}
		}
	}
	
}
